;;; A stimulus-input-feedback template

(in-package :experiment)

(defclass stimulus-input-feedback (exp:state)
  ((task-time :initform 0 :initarg :task-time :accessor task-time)
   (wrong-feedback-time :initform 10 :initarg :wrong-feedback-time :accessor wrong-feedback-time)
   (correct-feedback-time :initform 2 :initarg :correct-feedback-time :accessor correct-feedback-time)))

(defgeneric show-answer (state timeout))
(defgeneric do-feedback (state timeout))

(defmethod exp:state-dump append (exp (state stimulus-input-feedback))
  `(:task-time ,(task-time state)
    :wrong-feedback-time ,(wrong-feedback-time state)
    :correct-feedback-time ,(correct-feedback-time state)))

(defmethod state-list-actions append (exp (state stimulus-input-feedback))
  (declare (ignore exp))
  (default-list-actions state))

(defmethod state-init :after (exp (state stimulus-input-feedback))
  (when (plusp (task-time state))
    (exp:start-timer (task-time state) :tag :task)))

(defmethod do-feedback ((state stimulus-input-feedback) timed-out)
  (when timed-out (exp:lg 'timeout))
  (let ((wrong (show-answer state timed-out)))
    (exp:cancel-state-timers exp:*experiment* state)
    (if wrong
        (exp:start-timer (wrong-feedback-time state) :tag :feedback)
        (exp:start-timer (correct-feedback-time state) :tag :feedback))))

(define-action feedback-timeout ((state stimulus-input-feedback)
                                 (timeout :tag :feedback))
     (exp:state-onward *experiment* state))

(define-action task-timeout ((state stimulus-input-feedback)
                             (timeout :tag :task))
  (do-feedback state t))
